﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Controls;
using System.Windows.Forms;
using CapstoneProjectAEReader.GUIs.LibraryGUI;
using CapstoneProjectAEReader.Entities.Models;
using CapstoneProjectAEReader.Common.Utility;
using CapstoneProjectAEReader.DataAccess.DBAccess;
using CapstoneProjectAEReader.GUIs.ReaderGUI;
using Button = System.Windows.Controls.Button;
using MessageBox = System.Windows.Forms.MessageBox;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
using Path = System.IO.Path;
using CapstoneProjectAEReader.Business.Others;
using Message = CapstoneProjectAEReader.GUIs.LibraryGUI.Message;
using TabControl = System.Windows.Forms.TabControl;

namespace CapstoneProjectAEReader.GUIs
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    /// 
    public partial class MainWindow : Window
    {
        #region Attributes

        //const strings
        private const string GeneralTabName = "generalTab";
        private const string EbookTabName = "ebookTab";
        private const string NoteTabName = "noteTab";
        private const string SettingName = "settingTab";
        private const string OpenFileName = "openFileButton";
        private const string ImportFilesName = "importFilesButton";
        private const string ExitName = "exitButton";
        private const string OpenEbook = "statusOpenind";
        private const string TabHeader = "TabHeader";
        private const string OpeningEbookError = "openingEbookError";
        private const string MaxTabNumber = "maxTabError";

        private LibraryGUI.LocalLibrary _library;
        private DictionaryGUI.NoteManagement _noteManagement;
        private SettingGUI.Setting _setting;
        private SyncManager _syncManager;
        private List<TabItem> _tabItems;
        private DTO _dto;
        private readonly FileHandler _fileHandler = new FileHandler();
        private string _currentTabHeader;
        private Dictionary<string, ReaderGUI.ReaderGui> _openingEbook = new Dictionary<string, ReaderGui>();

        public string[] ArrNoteDetail;

        public NoteDetail NoteDetailData;
        //Binding To New Control
        private GetHeaderText _getHeaderTextClass;

        #endregion

        public GetHeaderText HeaderClass
        {
            get { return _getHeaderTextClass; }
        }

        public class GetHeaderText
        {
            public string GeneralTabString
            {
                get { return ResourceReader.GetResourceContent(GeneralTabName); }
            }

            public string EBookString
            {
                get { return ResourceReader.GetResourceContent(EbookTabName); }
            }

            public string NoteString
            {
                get { return ResourceReader.GetResourceContent(NoteTabName); }
            }

            public string SettingString
            {
                get { return ResourceReader.GetResourceContent(SettingName); }
            }

            public string OpenString
            {
                get { return ResourceReader.GetResourceContent(OpenFileName); }
            }

            public string ImportString
            {
                get { return ResourceReader.GetResourceContent(ImportFilesName); }
            }

            public string ExitString
            {
                get { return ResourceReader.GetResourceContent(ExitName); }
            }
        }

        public LocalLibrary Library
        {
            get { return _library; }
            set { _library = value; }
        }

        public MainWindow()
        {
            InitializeComponent();
            System.Windows.Forms.Clipboard.Clear();
            _tabItems = new List<TabItem>();
            Utilities.BuildDirectoryStructure();
            _syncManager = new SyncManager(1);
            //Initiate DTO
            if (Utilities.CheckFileExist(Constants.StorageStructure.ApplicationData))
            {
                _dto = _fileHandler.ReadFile(Constants.StorageStructure.ApplicationData);
            }
            else
            {
                _dto = new DTO
                           {
                               SettingDetail =
                                   {
                                       ApplicationLanguage = Constants.SettingSupporter.Vietnamese,
                                       FontSize = 10,
                                       SelectedFontType = "",
                                       ReadingMode = Constants.SettingSupporter.DayReadingMode
                                   }
                           };
                var unGroup = new EbookGroup {Groupid = 0, Groupname = Constants.UnGroup};
                _dto.EbookGroup.Add(unGroup);
                DAO.CommitData(_dto);
            }

            //Initiate language object
            ResourceReader.Initialize(_dto.SettingDetail.ApplicationLanguage);
            ReloadFormLanguage();

            //Load Form title
            Title = Constants.ApplicationTitle;
            OpenEbookTab();
        }


        public DTO Dto
        {
            get { return _dto; }
            set { _dto = value; }
        }

        /// <summary>
        /// Reload form language base on settings
        /// </summary>
        public void ReloadFormLanguage()
        {
            _getHeaderTextClass = new GetHeaderText();
        }

        private string CreateNewTagName()
        {
            string tabName = Utilities.GenerateRandomString();
            while (_tabItems.Any(x => x.Name == tabName))
            {
                tabName = Utilities.GenerateRandomString();
            }
            return tabName;
        }

        private void ImportHandler(object sender, RoutedEventArgs e)
        {
            SyncManager mySync = new SyncManager(1);
            _dto = mySync.SyncDB(_dto);
            String tabheader = ResourceReader.GetResourceContent(EbookTabName);
            RemoveEbookTabWithHeader(tabheader);
            OpenEbookTab();
        }

        private void OpenFileHandler(object sender, RoutedEventArgs e)
        {
            if (CheckMaxTabNumber())
            {
                string tabheader = Constants.CommonCharacters.Empty;
                try
                {
                    OpenFileDialog myOpenFileDg = new OpenFileDialog();
                    myOpenFileDg.Filter = Constants.FileFilter.PdfEpub;
                    if (myOpenFileDg.ShowDialog() == true)
                    {
                        FileInfo myFile = new FileInfo(myOpenFileDg.FileName);
                        tabheader = Path.GetFileNameWithoutExtension(myFile.Name);
                        // check if the tab already opened
                        if (!CheckTabExist(tabheader))
                        {
                            int count = _tabItems.Count;

                            // add new tabItem 
                            TabItem tab = new TabItem();
                            tab.Header = tabheader;
                            tab.Name = CreateNewTagName();
                            tab.HeaderTemplate = tabDynamic.FindResource(TabHeader) as DataTemplate;

                            // add tab into list tab items
                            _tabItems.Insert(count, tab);

                            // bind tab control
                            tabDynamic.Items.Add(tab);

                            // select newly added tab item
                            tabDynamic.SelectedItem = tab;

                            // add controls to tab item
                            string fileName = Path.GetFileName(myFile.FullName);
                            ReaderGUI.ReaderGui reader = new ReaderGUI.ReaderGui(myFile.FullName, _dto);
                            _openingEbook.Add(tabheader, reader);
                            Grid readerTab = reader.GetReaderTab();
                            tab.Content = readerTab;
                            tab.Tag = reader;
                        }
                    }
                }
                catch (Exception ex)
                {
                    if(_openingEbook.ContainsKey(tabheader)){_openingEbook.Remove(tabheader);}
                    RemoveEbookTabWithHeader(tabheader);
                    if (Constants.CommonCharacters.Empty != ex.Message)
                    {
                        Utilities.ShowErrorMesBox(String.Format(ResourceReader.GetResourceContent(OpeningEbookError),
                                                                ex.Message));
                    }
                }
            }
        }

        public void OpenNewEbook(string filePath, int pageNo)
        {
            if (CheckMaxTabNumber())
            {
                FileInfo myFile = new FileInfo(filePath);
                string tabheader = Path.GetFileNameWithoutExtension(myFile.Name);
                try
                {
                    // check if the tab already opened
                    if (!CheckTabExist(tabheader))
                    {
                        int count = _tabItems.Count;

                        // add new tabItem 
                        TabItem tab = new TabItem();
                        tab.Header = tabheader;
                        tab.Name = CreateNewTagName();
                        tab.HeaderTemplate = tabDynamic.FindResource(TabHeader) as DataTemplate;

                        // add tab into list tab items
                        _tabItems.Insert(count, tab);

                        // bind tab control
                        tabDynamic.Items.Add(tab);

                        // select newly added tab item
                        tabDynamic.SelectedItem = tab;

                        // add controls to tab item
                        ReaderGui reader = new ReaderGui(myFile.FullName, _dto, pageNo);
                        _openingEbook.Add(tabheader, reader);
                        Grid readerTab = reader.GetReaderTab();
                        tab.Content = readerTab;
                        tab.Tag = reader;
                        tabDynamic.SelectedIndex = GetIndexOfSelectedItem(tabheader);
                        //Move to page
                    }
                    else
                    {
                        int index = GetIndexOfSelectedItem(tabheader);
                        tabDynamic.SelectedItem = index;
                        tabDynamic.SelectedIndex = index;
                    }
                }
                catch (Exception ex)
                {
                    if (_openingEbook.ContainsKey(tabheader))
                    {
                        _openingEbook.Remove(tabheader);
                    }
                    RemoveEbookTabWithHeader(tabheader);
                    if (Constants.CommonCharacters.Empty != ex.Message)
                    {
                        Utilities.ShowErrorMesBox(String.Format(ResourceReader.GetResourceContent(OpeningEbookError),
                                                                ex.Message));
                    }
                }
            }
        }

        public void ReloadEbookTabLanguage(string oldTabHeader)
        {
            if (CheckTabExist(oldTabHeader))
            {
                int index = GetIndexOfSelectedItem(oldTabHeader);
                TabItem ebookTab = (TabItem) tabDynamic.Items[index];
                ebookTab.Header = ResourceReader.GetResourceContent(EbookTabName);
                _library.ReloadFormLanguage();
            }
        }

        //Add EBook
        private void OpenEBookTab(object sender, RoutedEventArgs e)
        {
            String tabheader = ResourceReader.GetResourceContent(EbookTabName);
            // check if the tab already opened
            if (!CheckTabExist(tabheader))
            {
                int count = _tabItems.Count;

                // add new tabItem 
                TabItem tab = new TabItem();
                tab.Header = tabheader;
                tab.Name = CreateNewTagName();
                tab.HeaderTemplate = tabDynamic.FindResource(TabHeader) as DataTemplate;


                // add controls to tab item
                _library = new LibraryGUI.LocalLibrary(_dto, this);
                Grid libraryTab = _library.GetLibraryTab();
                tab.Content = libraryTab;

                // add tab into list tab items
                _tabItems.Insert(count, tab);

                // bind tab control
                tabDynamic.Items.Add(tab);

                // select newly added tab item
                tabDynamic.SelectedItem = tab;
            }
            else
            {
                _library.RebindBookListData(_library.GetCheckedItem());
                _library.RebindRecentReadData();
                tabDynamic.SelectedIndex = GetIndexOfSelectedItem(tabheader);
            }
        }

        private void OpenEbookTab()
        {
            String tabheader = ResourceReader.GetResourceContent(EbookTabName);
            // check if the tab already opened
            if (!CheckTabExist(tabheader))
            {
                int count = _tabItems.Count;
                // add new tabItem 
                TabItem tab = new TabItem();
                tab.Header = ResourceReader.GetResourceContent(EbookTabName);
                tab.Name = CreateNewTagName();
                tab.HeaderTemplate = tabDynamic.FindResource(TabHeader) as DataTemplate;


                // add controls to tab item
                _library = new LibraryGUI.LocalLibrary(_dto, this);
                Grid libraryTab = _library.GetLibraryTab();
                tab.Content = libraryTab;

                // add tab into list tab items
                _tabItems.Insert(count, tab);

                // bind tab control
                tabDynamic.Items.Add(tab);

                // select newly added tab item
                tabDynamic.SelectedItem = tab;
            }
            else
            {
                _library.RebindGroupData();
                _library.RebindBookListData(_library.GetCheckedItem());
                _library.RebindRecentReadData();
                tabDynamic.SelectedIndex = GetIndexOfSelectedItem(tabheader);
            }
        }

        public void ReloadNoteTabLanguage(string oldTabHeader)
        {
            if (CheckTabExist(oldTabHeader))
            {
                int index = GetIndexOfSelectedItem(oldTabHeader);
                TabItem noteTab = (TabItem) tabDynamic.Items[index];
                noteTab.Header = ResourceReader.GetResourceContent(NoteTabName);
                _noteManagement.ReloadFormLanguage();
            }
        }

        //Add Note
        private void OpenNoteTab(object sender, RoutedEventArgs e)
        {
            String tabheader = ResourceReader.GetResourceContent(NoteTabName);
            // check if the tab already opened
            if (!CheckTabExist(tabheader))
            {
                int count = _tabItems.Count;

                // add new tabItem 
                TabItem tab = new TabItem();
                tab.Header = tabheader;
                tab.Name = CreateNewTagName();
                tab.HeaderTemplate = tabDynamic.FindResource(TabHeader) as DataTemplate;


                // add controls to tab item
                _noteManagement = new DictionaryGUI.NoteManagement(_dto, this);
                Grid noteMangementTab = _noteManagement.GetNoteManagementTab();
                tab.Content = noteMangementTab;

                // add tab into list tab items
                _tabItems.Insert(count, tab);

                // bind tab control
                tabDynamic.Items.Add(tab);

                // select newly added tab item
                tabDynamic.SelectedItem = tab;
            }
            else
            {
                if (String.IsNullOrEmpty(_noteManagement.txtSearch.Text))
                {
                    _noteManagement.RebindNoteList(_dto.Note);
                }
                tabDynamic.SelectedIndex = GetIndexOfSelectedItem(tabheader);
            }
        }

        public void ReloadSettingTabLanguage(string oldTabHeader)
        {
            if (CheckTabExist(oldTabHeader))
            {
                int index = GetIndexOfSelectedItem(oldTabHeader);
                TabItem settingTab = (TabItem) tabDynamic.Items[index];
                settingTab.Header = ResourceReader.GetResourceContent(SettingName);
                _setting.ReloadFormLanguage();
            }
        }

        public void ReloadEbooksTabLanguage()
        {
            foreach (string tempHeader in _openingEbook.Keys)
            {
                if (CheckTabExist(tempHeader))
                {
                    _openingEbook[tempHeader].ReloadFormLanguage();
                }
            }
        }

        //Add Setting
        private void OpenSettingTab(object sender, RoutedEventArgs e)
        {
            String tabheader = ResourceReader.GetResourceContent(SettingName);
            // check if the tab already opened
            if (!CheckTabExist(tabheader))
            {
                int count = _tabItems.Count;

                // add new tabItem 
                TabItem tab = new TabItem();
                tab.Header = tabheader;
                tab.Name = CreateNewTagName();
                tab.HeaderTemplate = tabDynamic.FindResource(TabHeader) as DataTemplate;

                // add controls to tab item
                _setting = new SettingGUI.Setting(_dto, this);
                Grid gSettingTab = _setting.GetSettingTab();
                tab.Content = gSettingTab;

                // add tab into list tab items
                _tabItems.Insert(count, tab);

                // bind tab control
                tabDynamic.Items.Add(tab);

                // select newly added tab item
                tabDynamic.SelectedItem = tab;
            }
            else
            {
                tabDynamic.SelectedIndex = GetIndexOfSelectedItem(tabheader);
            }
        }

        public bool CheckTabExist(String tabHeader)
        {
            bool flag = false;
            for (int i = 0; i < _tabItems.Count; i++)
            {
                String tabItemCompared = _tabItems.ElementAt(i).Header.ToString();
                if (tabHeader.Equals(tabItemCompared))
                {
                    flag = true;
                }
            }
            return flag;
        }

        private int GetIndexOfSelectedItem(string tabHeader)
        {
            for (int i = 0; i < _tabItems.Count; i++)
            {
                string tabItemCompared = _tabItems.ElementAt(i).Header.ToString();
                if (tabItemCompared.Equals(tabHeader))
                {
                    return i;
                }
            }
            return -1;
        }

        private void BtnDeleteClick(object sender, RoutedEventArgs e)
        {
            Button button = sender as Button;
            if (button != null)
            {
                string tabName = button.CommandParameter.ToString();
                var item = tabDynamic.Items.Cast<TabItem>().Where(i => i.Name.Equals(tabName)).SingleOrDefault();

                var tab = item;

                if (tab != null)
                {
                    // get selected tab
                    TabItem selectedTab = tabDynamic.SelectedItem as TabItem;

                    // clear tab control binding
                    //tabDynamic.DataContext = null;
                    var getTabItemContent = (Window) tab.Tag;
                    if (getTabItemContent != null)
                    {
                        getTabItemContent.Close();
                    }
                    if (_openingEbook.ContainsKey(selectedTab.Header.ToString()))
                    {
                        _openingEbook.Remove(selectedTab.Header.ToString());
                    }
                    _tabItems.Remove(tab);

                    // bind tab control
                    tabDynamic.Items.Remove(tab);

                    // select previously selected tab. if that is removed then select first tab
                    if (selectedTab == null || selectedTab.Equals(tab))
                    {
                        if (_tabItems.Count != 0)
                        {
                            selectedTab = _tabItems[0];
                        }
                    }
                    tabDynamic.SelectedItem = selectedTab;
                }
            }
        }

        public void CloseAllTab()
        {
            List<TabItem> tempDeletedItems = new List<TabItem>(_tabItems);
            foreach (TabItem tempTabItem in tempDeletedItems)
            {
                _tabItems.Remove(tempTabItem);
            }
            tempDeletedItems = new List<TabItem>();
            foreach (TabItem temp in tabDynamic.Items)
            {
                tempDeletedItems.Add(temp);
            }
            tempDeletedItems = new List<TabItem>(tempDeletedItems);
            foreach (TabItem temp in tempDeletedItems)
            {
                tabDynamic.Items.Remove(temp);
            }
            _openingEbook = new Dictionary<string, ReaderGui>();
            OpenEbookTab();
        }

        public void RemoveEbookTabWithHeader(string header)
        {
            TabItem deletedTab = _tabItems.Find(e => header == e.Header.ToString());
            int index = GetIndexOfSelectedItem(header);
            if (_tabItems.Contains(deletedTab))
            {
                _tabItems.Remove(deletedTab);
                tabDynamic.Items.RemoveAt(index);
            }
        }

        private void WindowClosedHandler(object sender, EventArgs e)
        {
            System.Windows.Clipboard.Clear();
            //Utilities.CopyFile(strXmlOldPath, _ebook.BookmarkPath);
            Utilities.ClearTempFolder();
            System.Windows.Application.Current.Shutdown();
        }

        private void btExit_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Application.Current.Shutdown();
        }

        private bool CheckMaxTabNumber()
        {
            if (_openingEbook.Count == 5)
            {
                Utilities.ShowWarningMesbox(ResourceReader.GetResourceContent(MaxTabNumber));
                return false;
            }
            return true;
        }

        //public void SetStatus(string content)
        //{
        //    txtStatus.Content = content;
        //}

        private void HandleChangeTabItem(object sender, SelectionChangedEventArgs e)
        {
            if (tabDynamic.SelectedItem != null)
            {
                string tabHeader = "";
                TabItem selectedItem = (TabItem) tabDynamic.SelectedItem;
                if (selectedItem != null)
                {
                    tabHeader = selectedItem.Header.ToString();
                }
                if (_currentTabHeader != tabHeader)
                {
                    if (ResourceReader.GetResourceContent(EbookTabName).Equals(tabHeader))
                    {
                        if (_library != null)
                        {
                            _library.RebindBookListData(_library.GetCheckedItem());
                            _library.RebindGroupData();
                            _library.RebindRecentReadData();
                        }
                    }
                    if (ResourceReader.GetResourceContent(NoteTabName).Equals(tabHeader))
                    {
                        if (_noteManagement != null)
                        {
                            if (String.IsNullOrEmpty(_noteManagement.txtSearch.Text))
                            {
                                _noteManagement.RebindNoteList(_dto.Note);
                            }
                        }
                    }
                    tabDynamic.SelectedIndex = GetIndexOfSelectedItem(tabHeader);
                    _currentTabHeader = tabHeader;
                }
            }
        }
    }
}